package cn.wk.user.service.impl;

import cn.wk.basic.constant.ConstantPethome;
import cn.wk.basic.constant.ConstantVerification;
import cn.wk.basic.exception.DiyException;
import cn.wk.basic.utils.AjaxResult;
import cn.wk.basic.utils.MD5Utils;
import cn.wk.basic.utils.StrUtils;
import cn.wk.user.domain.LoginInfo;
import cn.wk.user.domain.User;
import cn.wk.user.domain.dto.LoginInfoDto;
import cn.wk.user.mapper.LoginInfoMapper;
import cn.wk.user.mapper.UserMapper;
import cn.wk.user.service.ILoginInfoService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class LoginInfoServiceImpl implements ILoginInfoService {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private LoginInfoMapper loginInfoMapper;

    @Autowired
    private UserMapper userMapper;

    /**
     * 注册功能
     * @param loginInfoDto 传入前端输入的数据
     * @throws DiyException
     */
    @Override
    public void register(LoginInfoDto loginInfoDto) throws DiyException {
        //校验数据
        checkRegData(loginInfoDto);
        //创建logininfo对象，然后保存
        LoginInfo logInfo = creatLoginInfo(loginInfoDto);
        loginInfoMapper.save(logInfo);
        //创建user对象，然后保存
        User user = creatUser(logInfo);
        userMapper.save(user);
    }

    /**
     * 登录功能
     * @param loginInfoDto
     */
    @Override
    public AjaxResult login(LoginInfoDto loginInfoDto) throws DiyException {
        //进行校验数据
        checkLoginData(loginInfoDto);
        //根据传进来的用户名和type去数据库查询数据
        LoginInfo loginInfo = loginInfoMapper.findByNameAndType(loginInfoDto.getUsername(),loginInfoDto.getType());
        //判断用户是否存在
        if(loginInfo == null){
            throw new DiyException("该用户不存在");
        }else if(!loginInfo.getPassword().equals(MD5Utils.encrypByMd5(loginInfoDto
                .getPassword()+loginInfo.getSalt()))){
            throw new DiyException("密码错误");
        }
        //随机生成一个token
        String token = UUID.randomUUID().toString();
        //把随机生成的token和用户信息放进redis中去，并设置时长为30分钟
        redisTemplate.opsForValue().set(token,loginInfo,30, TimeUnit.MINUTES);
        //返回到前台去
        //这里为了方便把用户信息也一起返回到前台（返回用户信息是不安全的）
        HashMap<String, Object> map = new HashMap<>();
        map.put("token",token);
        map.put("loginUser",loginInfo);
        return new AjaxResult().setResultObj(map);
    }

    /**
     * 检验登录数据
     * @param loginInfoDto
     */
    private void checkLoginData(LoginInfoDto loginInfoDto) throws DiyException {
        if(StringUtils.isEmpty(loginInfoDto.getUsername())){
            throw new DiyException("登录名必须输入");
        }
        if(StringUtils.isEmpty(loginInfoDto.getPassword())){
            throw new DiyException("密码必须输入！");
        }
        if(loginInfoDto.getType() == null){
            throw new DiyException("请完善信息！");
        }
    }

    /**
     * 创建user对象
     * @param logInfo
     * @return
     */
    private User creatUser(LoginInfo logInfo) {
        User user = new User();
        BeanUtils.copyProperties(logInfo,user);
        //给user设置状态
        user.setState(ConstantPethome.OK);
        //把logininfo设置到user里面去
        user.setLogininfo(logInfo);
        return user;
    }

    /**
     * 创建logininfo对象
     * @param loginInfoDto
     * @return
     */
    private LoginInfo creatLoginInfo(LoginInfoDto loginInfoDto) {
        LoginInfo logInfo = new LoginInfo();
        //设置手机号
        logInfo.setPhone(loginInfoDto.getPhone());
        //设置盐值，用随机数生成
        String random = StrUtils.getComplexRandomString(10);
        logInfo.setSalt(random);
        //设置密码，并用md5加密
        logInfo.setPassword(MD5Utils.encrypByMd5(loginInfoDto.getPassword()+random));
        //设置用户类型
        logInfo.setType(loginInfoDto.getType());
        return logInfo;
    }


    /**
     * 校验注册数据
     * @param loginInfoDto
     * @throws DiyException
     */
    private void checkRegData(LoginInfoDto loginInfoDto) throws DiyException {
        //校验手机号
        if(StringUtils.isEmpty(loginInfoDto.getPhone())){
            throw new DiyException("手机号必填");
        }
        //判断手机号是否重复
        User user = userMapper.findByPhone(loginInfoDto.getPhone());
        if(user != null){
            throw new DiyException("该手机号已被注册");
        }
        //判断验证码是否为空
        if(StringUtils.isEmpty(loginInfoDto.getCode())){
            throw new DiyException("验证码为空");
        }
        //判断验证码是否过期
        String codeVal= (String)redisTemplate.opsForValue().get(loginInfoDto.getPhone()+":"+ConstantVerification.USE_REG);
        if(StringUtils.isEmpty(codeVal)){
            throw new DiyException("验证码已过期，请重新获取");
        }
        //判断验证码是否匹配
        if(!codeVal.split(":")[0].toUpperCase().equals(loginInfoDto.getCode().toUpperCase())){
            throw new DiyException("验证码输入错误，请重新输入");
        }
        //是否填写了密码
        if(StringUtils.isEmpty(loginInfoDto.getPassword())){
            throw new DiyException("请填写密码");
        }
        //两次输入密码是否一样
        if(!loginInfoDto.getPassword().equals(loginInfoDto.getConfigPassword())){
            throw new DiyException("两次密码输入不一样");
        }
    }
}
